// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.spnetwork;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import se.krka.kahlua.vm.KahluaTable;
import se.krka.kahlua.vm.KahluaTableIterator;
import zombie.Lua.LuaEventManager;
import zombie.Lua.LuaManager;
import zombie.characters.IsoPlayer;
import zombie.core.network.ByteBufferWriter;
import zombie.debug.DebugLog;
import zombie.globalObjects.SGlobalObjectNetwork;
import zombie.iso.IsoObject;
import zombie.iso.objects.IsoWorldInventoryObject;
import zombie.network.GameClient;
import zombie.network.PacketTypes;
import zombie.network.TableNetworkUtils;
import zombie.vehicles.BaseVehicle;

public final class SinglePlayerServer {
    private static final ArrayList<ZomboidNetData> MainLoopNetData = new ArrayList();
    public static final SinglePlayerServer.UdpEngineServer udpEngine = new SinglePlayerServer.UdpEngineServer();

    public static void addIncoming(short id, ByteBuffer bb, UdpConnection connection) {
        ZomboidNetData zomboidNetData;
        if (bb.remaining() > 2048) {
            zomboidNetData = ZomboidNetDataPool.instance.getLong(bb.remaining());
        } else {
            zomboidNetData = ZomboidNetDataPool.instance.get();
        }

        zomboidNetData.read(id, bb, connection);
        synchronized (MainLoopNetData) {
            MainLoopNetData.add(zomboidNetData);
        }
    }

    private static void sendObjectChange(IsoObject isoObject, String string, KahluaTable kahluaTable, UdpConnection udpConnection) {
        if (isoObject.getSquare() != null) {
            ByteBufferWriter byteBufferWriter = udpConnection.startPacket();
            PacketTypes.PacketType.ObjectChange.doPacket(byteBufferWriter);
            if (isoObject instanceof IsoPlayer) {
                byteBufferWriter.putByte((byte)1);
                byteBufferWriter.putShort(((IsoPlayer)isoObject).OnlineID);
            } else if (isoObject instanceof BaseVehicle) {
                byteBufferWriter.putByte((byte)2);
                byteBufferWriter.putShort(((BaseVehicle)isoObject).getId());
            } else if (isoObject instanceof IsoWorldInventoryObject) {
                byteBufferWriter.putByte((byte)3);
                byteBufferWriter.putInt(isoObject.getSquare().getX());
                byteBufferWriter.putInt(isoObject.getSquare().getY());
                byteBufferWriter.putInt(isoObject.getSquare().getZ());
                byteBufferWriter.putInt(((IsoWorldInventoryObject)isoObject).getItem().getID());
            } else {
                byteBufferWriter.putByte((byte)0);
                byteBufferWriter.putInt(isoObject.getSquare().getX());
                byteBufferWriter.putInt(isoObject.getSquare().getY());
                byteBufferWriter.putInt(isoObject.getSquare().getZ());
                byteBufferWriter.putInt(isoObject.getSquare().getObjects().indexOf(isoObject));
            }

            byteBufferWriter.putUTF(string);
            isoObject.saveChange(string, kahluaTable, byteBufferWriter.bb);
            udpConnection.endPacketImmediate();
        }
    }

    public static void sendObjectChange(IsoObject isoObject, String string, KahluaTable kahluaTable) {
        if (isoObject != null) {
            for (int _int = 0; _int < udpEngine.connections.size(); _int++) {
                UdpConnection udpConnection = (UdpConnection)udpEngine.connections.get(_int);
                if (udpConnection.ReleventTo(isoObject.getX(), isoObject.getY())) {
                    sendObjectChange(isoObject, string, kahluaTable, udpConnection);
                }
            }
        }
    }

    public static void sendObjectChange(IsoObject isoObject, String string, Object... object0) {
        if (object0.length == 0) {
            sendObjectChange(isoObject, string, (KahluaTable)null);
        } else if (object0.length % 2 == 0) {
            KahluaTable kahluaTable = LuaManager.platform.newTable();

            for (byte _byte = 0; _byte < object0.length; _byte += 2) {
                Object object1 = object0[_byte + 1];
                if (object1 instanceof Float) {
                    kahluaTable.rawset(object0[_byte], ((Float)object1).doubleValue());
                } else if (object1 instanceof Integer) {
                    kahluaTable.rawset(object0[_byte], ((Integer)object1).doubleValue());
                } else if (object1 instanceof Short) {
                    kahluaTable.rawset(object0[_byte], ((Short)object1).doubleValue());
                } else {
                    kahluaTable.rawset(object0[_byte], object1);
                }
            }

            sendObjectChange(isoObject, string, kahluaTable);
        }
    }

    public static void sendServerCommand(String string0, String string1, KahluaTable kahluaTable, UdpConnection udpConnection) {
        ByteBufferWriter byteBufferWriter = udpConnection.startPacket();
        PacketTypes.PacketType.ClientCommand.doPacket(byteBufferWriter);
        byteBufferWriter.putUTF(string0);
        byteBufferWriter.putUTF(string1);
        if (kahluaTable != null && !kahluaTable.isEmpty()) {
            byteBufferWriter.putByte((byte)1);

            try {
                KahluaTableIterator kahluaTableIterator = kahluaTable.iterator();

                while (kahluaTableIterator.advance()) {
                    if (!TableNetworkUtils.canSave(kahluaTableIterator.getKey(), kahluaTableIterator.getValue())) {
                        DebugLog.log("ERROR: sendServerCommand: can't save key,value=" + kahluaTableIterator.getKey() + "," + kahluaTableIterator.getValue());
                    }
                }

                TableNetworkUtils.save(kahluaTable, byteBufferWriter.bb);
            } catch (IOException iOException) {
                iOException.printStackTrace();
            }
        } else {
            byteBufferWriter.putByte((byte)0);
        }

        udpConnection.endPacketImmediate();
    }

    public static void sendServerCommand(String string0, String string1, KahluaTable kahluaTable) {
        for (int _int = 0; _int < udpEngine.connections.size(); _int++) {
            UdpConnection udpConnection = (UdpConnection)udpEngine.connections.get(_int);
            sendServerCommand(string0, string1, kahluaTable, udpConnection);
        }
    }

    public static void update() {
        if (!GameClient.bClient) {
            for (short _short = 0; _short < IsoPlayer.numPlayers; _short++) {
                if (IsoPlayer.players[_short] != null) {
                    IsoPlayer.players[_short].setOnlineID(_short);
                }
            }

            synchronized (MainLoopNetData) {
                for (int _int = 0; _int < MainLoopNetData.size(); _int++) {
                    ZomboidNetData zomboidNetData = (ZomboidNetData)MainLoopNetData.get(_int);
                    mainLoopDealWithNetData(zomboidNetData);
                    MainLoopNetData.remove(_int--);
                }
            }
        }
    }

    private static void mainLoopDealWithNetData(ZomboidNetData zomboidNetData) {
        ByteBuffer byteBuffer = zomboidNetData.buffer;

        try {
            PacketTypes.PacketType packetType = (PacketTypes.PacketType)PacketTypes.packetTypes.get(zomboidNetData.type);
            switch (packetType) {
                case ClientCommand:
                    receiveClientCommand(byteBuffer, zomboidNetData.connection);
                    break;
                case GlobalObjects:
                    receiveGlobalObjects(byteBuffer, zomboidNetData.connection);
            }
        } finally {
            ZomboidNetDataPool.instance.discard(zomboidNetData);
        }
    }

    private static IsoPlayer getAnyPlayerFromConnection(UdpConnection udpConnection) {
        for (int _int = 0; _int < 4; _int++) {
            if (udpConnection.players[_int] != null) {
                return udpConnection.players[_int];
            }
        }

        return null;
    }

    private static IsoPlayer getPlayerFromConnection(UdpConnection udpConnection, int _int) {
        return _int >= 0 && _int < 4 ? udpConnection.players[_int] : null;
    }

    private static void receiveClientCommand(ByteBuffer byteBuffer, UdpConnection udpConnection) {
        byte _byte = byteBuffer.get();
        String string0 = zombie.GameWindow.ReadString(byteBuffer);
        String string1 = zombie.GameWindow.ReadString(byteBuffer);
        boolean _boolean = byteBuffer.get() == 1;
        KahluaTable kahluaTable = null;
        if (_boolean) {
            kahluaTable = LuaManager.platform.newTable();

            try {
                TableNetworkUtils.load(kahluaTable, byteBuffer);
            } catch (Exception exception) {
                exception.printStackTrace();
                return;
            }
        }

        IsoPlayer isoPlayer = getPlayerFromConnection(udpConnection, _byte);
        if (_byte == -1) {
            isoPlayer = getAnyPlayerFromConnection(udpConnection);
        }

        if (isoPlayer == null) {
            DebugLog.log("receiveClientCommand: player is null");
        } else {
            LuaEventManager.triggerEvent("OnClientCommand", string0, string1, isoPlayer, kahluaTable);
        }
    }

    private static void receiveGlobalObjects(ByteBuffer byteBuffer, UdpConnection udpConnection) {
        byte _byte = byteBuffer.get();
        IsoPlayer isoPlayer = getPlayerFromConnection(udpConnection, _byte);
        if (_byte == -1) {
            isoPlayer = getAnyPlayerFromConnection(udpConnection);
        }

        if (isoPlayer == null) {
            DebugLog.log("receiveGlobalObjects: player is null");
        } else {
            SGlobalObjectNetwork.receive(byteBuffer, isoPlayer);
        }
    }

    public static void Reset() {
        for (ZomboidNetData zomboidNetData : MainLoopNetData) {
            ZomboidNetDataPool.instance.discard(zomboidNetData);
        }

        MainLoopNetData.clear();
    }

    public static final class UdpEngineServer extends UdpEngine {
        public final ArrayList<UdpConnection> connections = new ArrayList();

        UdpEngineServer() {
            this.connections.add(new UdpConnection(this));
        }

        @Override
        public void Send(ByteBuffer bb) {
            SinglePlayerClient.udpEngine.Receive(bb);
        }

        @Override
        public void Receive(ByteBuffer bb) {
            int _int = bb.get() & 255;
            short _short = bb.getShort();
            SinglePlayerServer.addIncoming(_short, bb, (UdpConnection)SinglePlayerServer.udpEngine.connections.get(0));
        }
    }
}
